package com.wangsh.splider.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPicture;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.springframework.stereotype.Component;

import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;

/**
 * poi相关的工具类
 * 
 * @author
 */
@Component("poiUtil")
public class POIUtil {
	@Resource
	private FileUtil fileUtil;

	/**
	 * 保存xls的方法
	 * 
	 * @param file 文件的模板输入流;模板里面只有一行,就是title;主要是为了,区分列的顺序
	 * @param List List是行,里面的元素也是List;里面的Map;键是标题头,值是 真正的结果
	 */
	public void writeExcelModel(InputStream is, List dataList, OutputStream os)
	{
		/* 模板文件 */
		try
		{
			Workbook workbook = new HSSFWorkbook(is);
			/* 只要第一个sheet */
			Sheet sheet = workbook.getSheetAt(0);
			/* 读取标题的头部 */
			Row row = sheet.getRow(0);
			/* 存储所有的标题的头部 */
			Map<String, Integer> titleMap = new HashMap<String, Integer>();
			/* 取到每一列 */
			int titleCount = 0;
			for (Iterator iterator = row.cellIterator(); iterator.hasNext();)
			{
				Cell cellTemp = (Cell) iterator.next();
				titleMap.put(cellTemp.toString(), titleCount);
				titleCount++;
			}

			/*
			 * 存储数据 外循环是行 内循环是列
			 */
			int dataRow = 1;
			for (Iterator iterator = dataList.iterator(); iterator.hasNext();)
			{
				/*
				 * 取到row;模板中只有一行; 第二行
				 */
				Row row2 = sheet.createRow(dataRow);
				Map<String, Object> dataMap = (Map<String, Object>) iterator.next();

				/* 循环标题头部 */
				for (Iterator iterator2 = titleMap.entrySet().iterator(); iterator2.hasNext();)
				{
					/* 键:是xls中的标题的头部,值是列的顺序 */
					Entry me = (Entry) iterator2.next();
					/* 创建的单元格是几列,取决于titleMap中的值 */
					String key = me.getKey() + "";
					int value = Integer.valueOf(me.getValue() + "");

					/* 创建的是第几个单元格 */
					Cell cell = row2.createCell(value);
					/* 赋值的时候从dataMap中取值 */
					cell.setCellValue(dataMap.get(key) + "");
				}
				dataRow++;
			}

			/* 在保存文件的时候需要一个outputStream */
			workbook.write(os);
			/* 保存文件 */
			workbook.close();
		} catch (IOException e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("保存xls失败了;", e);
		}
	}

	/**
	 * 根据模板生成word文档
	 * @param is
	 * @param map image要传一个图片路径 
	 * @param os
	 */
	public void writeWordModel(InputStream is,Map<String, String> map,OutputStream os)
	{
		try
		{
			XWPFDocument document = new XWPFDocument(is);
			List<XWPFParagraph> paragraphList = document.getParagraphs() ; 
			/**
			 * 在循环的时候对数据进行处理
			 */
			for (Iterator iterator = paragraphList.iterator(); iterator.hasNext();)
			{
				XWPFParagraph xwpfParagraph = (XWPFParagraph) iterator.next();
				/* 获取每一行 */
				List<XWPFRun> runs = xwpfParagraph.getRuns();
				/* 设置内容 */
				for (Iterator iterator2 = runs.iterator(); iterator2.hasNext();)
				{
					XWPFRun xwpfRun = (XWPFRun) iterator2.next();
					/* 根据原来的字符串,修改模板 */
					String text = this.fileUtil.replaceOperator(xwpfRun.toString(), map);
					ConstatFinalUtil.SYS_LOGGER.info(xwpfRun.toString() + "==getParagraphs===>" + text + "===" + map);
					xwpfRun.setText(text,0);
				}
			}

			/* 表格 */
			List<XWPFTable> tableList = document.getTables();
			for (Iterator iterator = tableList.iterator(); iterator.hasNext();)
			{
				XWPFTable xwpfTable = (XWPFTable) iterator.next();
				/* 获取行 */
				List<XWPFTableRow> rowsList = xwpfTable.getRows();
				for (Iterator iterator2 = rowsList.iterator(); iterator2.hasNext();)
				{
					XWPFTableRow xwpfTableRow = (XWPFTableRow) iterator2.next();
					/* 获取单元格 */
					List<XWPFTableCell> tableCells = xwpfTableRow.getTableCells();
					for (Iterator iterator3 = tableCells.iterator(); iterator3.hasNext();)
					{
						XWPFTableCell xwpfTableCell = (XWPFTableCell) iterator3.next();
						/* 段落 */
						List<XWPFParagraph> paragraphTempList = xwpfTableCell.getParagraphs() ; 
						for (Iterator iterator4 = paragraphTempList.iterator(); iterator4.hasNext();)
						{
							XWPFParagraph xwpfParagraph = (XWPFParagraph) iterator4.next();
							/* 设置内容 */
							List<XWPFRun> runs = xwpfParagraph.getRuns();
							for (Iterator iterator5 = runs.iterator(); iterator5.hasNext();)
							{
								XWPFRun xwpfRun = (XWPFRun) iterator5.next();
								String souText = xwpfRun.toString() ; 
								if(souText.startsWith("${image"))
								{
									souText = souText.replaceAll("\\$", "").replaceAll("\\{", "").replaceAll("\\}", "");
									String path = map.get(souText);
									if(path != null)
									{
										File pathFile = new File(path);
										FileInputStream fis = new FileInputStream(path);
										if(souText.indexOf("_01") != -1)
										{
											/* 添加图片 */
											XWPFPicture picture = xwpfRun.addPicture(fis, XWPFDocument.PICTURE_TYPE_PNG, pathFile.getName(), 
													Units.toEMU(180), Units.toEMU(140));
										}else if(souText.indexOf("_02") != -1)
										{
											/* 添加图片 */
											XWPFPicture picture = xwpfRun.addPicture(fis, XWPFDocument.PICTURE_TYPE_PNG, pathFile.getName(), 
													Units.toEMU(220), Units.toEMU(143));
										}else
										{
											/* 添加图片 */
											XWPFPicture picture = xwpfRun.addPicture(fis, XWPFDocument.PICTURE_TYPE_PNG, pathFile.getName(), 
													Units.toEMU(100), Units.toEMU(100));
										}
										fis.close();
									}
									/* 清空单元格中的内容 */
									xwpfRun.setText("",0);
								}else
								{
									//System.out.println("====>" + souText);
									/* 根据原来的字符串,修改模板 */
									String text = this.fileUtil.replaceOperator(souText, map);
									/*ConstatFinalUtil.SYS_LOGGER.info(xwpfRun.toString() + "=Table=getParagraphs===>" + text + "===" + map
										+ "====picSize:" + xwpfRun.getPictureText() + "===" + xwpfRun.getEmbeddedPictures().size());*/
									xwpfRun.setText(text,0);
								}
							}
						}
					}
				}
			}

			/* 图片 
			List<XWPFPictureData> allPictureList = document.getAllPictures();
			for (Iterator iterator = allPictureList.iterator(); iterator.hasNext();)
			{
				XWPFPictureData xwpfPictureData = (XWPFPictureData) iterator.next();
				System.out.println("====" + xwpfPictureData.getFileName());
				byte[] picByte = xwpfPictureData.getData() ; 
				FileOutputStream fos = new FileOutputStream("d:/" + xwpfPictureData.getFileName());
				ByteInputStream bis = new ByteInputStream(picByte, picByte.length);
				 拷贝图片 
				this.fileUtil.copy(bis, fos,true);
			}*/

			/*List<XWPFPictureData> allPackagePictures = document.getAllPackagePictures();
			for (Iterator iterator = allPackagePictures.iterator(); iterator.hasNext();)
			{
				XWPFPictureData xwpfPictureData = (XWPFPictureData) iterator.next();
				System.out.println("====" + xwpfPictureData.getFileName());
			}

			https://blog.csdn.net/alice_qixin/article/details/71730346 
			try
			{
				FileInputStream fis = new FileInputStream(new File("d:/1.png"));
				String res = document.addPictureData(fis, XWPFDocument.PICTURE_TYPE_PNG);
				System.out.println("===>" + res);

				System.out.println("====" + document.getRelationById(res));
				CustomXWPFDocument customXWPFDocument = new CustomXWPFDocument(); 
				customXWPFDocument.createPicture(document.createParagraph(),document.getAllPictures().size()-1, 100, 100,"    ");
				fis.close();
				customXWPFDocument.close();
			} catch (InvalidFormatException e)
			{
				e.printStackTrace();
			}*/

			/* 将内容写到文件中 */
			document.write(os);
			document.close();
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("保存docx失败了;" ,e);
		} finally
		{
			/* 相关的流要关闭 */
			try
			{
				if(os != null)
				{
					os.close();
					os = null;  
				}
			} catch (IOException e)
			{
				ConstatFinalUtil.SYS_LOGGER.error("关闭失败了;", e);
			}
			try
			{
				if(is != null)
				{
					is.close();
					is = null;  
				}
			} catch (IOException e)
			{
				ConstatFinalUtil.SYS_LOGGER.error("关闭失败了;", e);
			}
		}
	}
	
	/**
	 * 读取xls文件内容  返回一个map集合
	 * @param 
	 * @throws IOException 
	 */

	public List<Map<String,Object>> readExcel(InputStream is,String extendName) throws IOException{
		Workbook workbook = null ; 
		//存放xls文件数据    
		List<Map<String,Object>> resultList = new ArrayList<>();
		try
		{
			if("xlsx".equalsIgnoreCase(extendName))
			{
				workbook = new XSSFWorkbook(is);
			}else
			{
				workbook = new HSSFWorkbook(is);
			}
			/* 只要第一个sheet */
			Sheet sheet = workbook.getSheetAt(0);
			/* 读取标题的头部 */
			Row row = sheet.getRow(0);
			/* 存储所有的标题的头部信息  key:序号  value:值 */
			Map<Integer,String> titleMap = new HashMap<Integer,String>();
			//存储数据 key:序号 value:数据
			Map<Integer,String> dataMap = new HashMap<Integer,String>();
			//获取总列数
			int columnNum = row.getPhysicalNumberOfCells();
			for (int titleCount = 0;titleCount < columnNum; titleCount++)
			{
				Cell cellTemp = row.getCell(titleCount);
				if(cellTemp != null)
				{
					titleMap.put(titleCount,cellTemp.toString());
				}
			}

			// 处理当前页，循环读取每一行  跳过title行  直接读取数据
			for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
				//存放xls文件中每一行的数据   Map中数据： key：title value：title值
				Map<String,Object> result = new HashMap<String,Object>();
				//			System.out.println(sheet.getLastRowNum());
				// HSSFRow表示行
				Row hssfRow = sheet.getRow(rowNum);
				int minColIx = hssfRow.getFirstCellNum();
				int maxColIx = hssfRow.getLastCellNum();
				// 遍历该行，获取处理每个cell元素
				for (int colIx = minColIx; colIx < maxColIx; colIx++) {
					// HSSFCell 表示单元格
					Cell cell = hssfRow.getCell(colIx);
					if (cell == null) {
						dataMap.put(colIx, null);
					}else {
						dataMap.put(colIx,cell.toString());
					}
					//遍历titleMap 和 valueMap 将key相同的value存储在同一个result集合中
					int titleKey = 0;
					int dataKey = 0;
					String titleValue = null;
					String dataValue = null;
					for(Map.Entry<Integer, String> entry : titleMap.entrySet()) { //遍历title
						//取出key和value
						titleKey = entry.getKey();
						titleValue = entry.getValue();
						for(Map.Entry<Integer, String> entry1 : dataMap.entrySet()) { //遍历data
							//取出key和value
							dataKey = entry1.getKey();
							dataValue = entry1.getValue();
							if(titleKey == dataKey) {
								result.put(titleValue, dataValue);
							}
						}
					}
				}
				resultList.add(result);
			}
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("读取文件报错了,扩展名:{}",extendName,e);
		}finally
		{
			if(workbook != null)
			{
				workbook.close();  
				workbook = null ; 
			}
			if(is != null)
			{
				is.close();  
				is = null ; 
			}
		}
		return resultList;
	}
	
	/**
	 * 读取文件内容
	 * 
	 * @param path 文件的完整路径
	 */
	public List<Map<String, String>> readFileCsv(String path)
	{
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		Map<String, String> map = null;
		if (path.endsWith(".csv"))
		{
			try
			{
				// 创建CSV读对象
				//CsvReader csvReader = new CsvReader(path, ',', Charset.forName("GBK"));
				CsvReader csvReader = new CsvReader(new FileInputStream(new File(path)), Charset.forName("GBK"));
				// 跳过表头
				csvReader.readHeaders();
				String[] headers = csvReader.getHeaders();
				while (csvReader.readRecord())
				{
					map = new LinkedHashMap<String, String>();
					for (int i = 0; i < headers.length; i++)
					{
						map.put(headers[i], csvReader.get(headers[i]));
					}
					list.add(map);
				}
			} catch (Exception e)
			{
				ConstatFinalUtil.SYS_LOGGER.error("读文件(csv)失败了,路径:{}",path,e);
			}
		}
		return list;
	}

	/**
	 * 写入csv文件的工具类
	 * 
	 * @param path要写入文件的路径
	 * @param headerList   标题信息,每个字段都代表第一行的列
	 * @param contentList  内容,外部的list代表一行,内圈的list代表每行的每一列
	 * 
	 */
	public void writeFileCsv(String path, List<String> headerList, List<List<String>> contentList)
	{
		CsvWriter csvWriter = new CsvWriter(path, ',', Charset.forName("GBK"));
		try
		{
			File file = new File(path);
			if (!file.exists())
			{
				if (!file.getParentFile().exists())
				{
					file.getParentFile().mkdirs();
				}
			}
			file.createNewFile();
			if (headerList != null && headerList.size() > 0)
			{
				String[] header = headerList.toArray(new String[0]);
				csvWriter.writeRecord(header);
			}
			if (contentList != null && contentList.size() > 0)
			{
				for (List<String> listContent : contentList)
				{
					if (listContent != null && listContent.size() > 0)
					{
						String[] array = listContent.toArray(new String[0]);
						csvWriter.writeRecord(array);
					}

				}
			}

		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("写文件(csv)失败了,路径:{}",path,e);
		} finally
		{
			csvWriter.close();
		}
	}
}
